package ru.ssau.customerManagement.controller.threads.server;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.ssau.customerManagement.controller.ServerSideController;
import ru.ssau.customerManagement.controller.remoting.OperationRequest;
import ru.ssau.customerManagement.controller.remoting.OperationResponse;
import ru.ssau.customerManagement.controller.remoting.RequestExecutor;
import ru.ssau.customerManagement.model.entities.Customer;
import ru.ssau.customerManagement.model.entities.CustomerLocation;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.net.SocketException;

/**
 * Created by illabefat on 25.11.14.
 */
public class Worker implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(Worker.class);

    private final Socket client;
    private final ServerSideController controller;
    private final RequestExecutor requestExecutor;

    public Worker(Socket client, ServerSideController controller) {
        this.client = client;
        this.controller = controller;
        requestExecutor = new RequestExecutor(controller);
    }

    @Override
    public void run() {
        try {
            Socket clientNotifier = new Socket(client.getInetAddress(), 4444);
            controller.addListener(clientNotifier);

            ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
            ObjectInputStream in = new ObjectInputStream(client.getInputStream());

            while (true)
            {
                JAXBContext jaxbContext1 = JAXBContext.newInstance(OperationResponse.class, OperationRequest.class,
                        Customer.class, CustomerLocation.class);
                Marshaller jaxbMarshaller = jaxbContext1.createMarshaller();
                Unmarshaller jaxbUnmarshaller = jaxbContext1.createUnmarshaller();

                String xmlRequest = in.readUTF();
                OperationRequest request = (OperationRequest) jaxbUnmarshaller.unmarshal(new StringReader(xmlRequest));
                OperationResponse response = requestExecutor.executeRequest(request);

                StringWriter sw = new StringWriter();
                jaxbMarshaller.marshal(response, sw);
                String xmlString = sw.toString();

                out.writeUTF(xmlString);

                out.flush();
                out.reset();
            }
        } catch (SocketException e) {
            logger.info("Client disconnected");
        } catch (IOException e) {
            e.printStackTrace();
        }    catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}
